package com.cdqidi.service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cdqidi.entity.SchoolCharge;
import com.cdqidi.entity.User;
import com.cdqidi.model.OrgWxconfig;
import com.cdqidi.util.RedisMgr;
import com.cdqidi.util.StaticResource;
import com.jfinal.core.Controller;
import com.jfinal.kit.HttpKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

public class AuthService {
	private static Logger logger = Logger.getLogger(AuthService.class);
	private final static String CHECKCAPTCHAURL=StaticResource.URL+"/weiXinManager/api/isCaptcha";
	private final Integer SEC=600;
	
	private AuthService(){
		
	}
	
	private static class SingletonHolder {
		private static AuthService INSTANCE = new AuthService();
	}
	
	public static AuthService getInstance() {
		return SingletonHolder.INSTANCE;
	}
	
	public void getCode(JSONObject json,String cid) {
		String code = UUID.randomUUID().toString();
		String id = "get_cid_code_"+cid+"_"+code;
		try {
			RedisMgr.getInstance().setProp(id, code);
			RedisMgr.getInstance().expire(id, 2*60);
		} catch (IOException e) {
			e.printStackTrace();
		}
		json.put("code", code);
	}
	
	public void authorize(String cid,String code,String param,JSONObject jo,Controller control) {
		if(StringUtils.isEmpty(code)||StringUtils.isEmpty(param)
				||StringUtils.isEmpty(param)) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "所有参数均不能为空");
			return;
		}
		boolean b = isValCode(cid, code);
		if(!b) {
			jo.put("errcode", 10004);
			jo.put("errmsg", "code错误");
		}
		User  user = null;
		try {
			 user = JSON.parseObject(param, User.class);
		}catch (Exception e) {
			jo.put("errcode", 10004);
			jo.put("errmsg", "param参数错误");
			return;
		}
		if(null==user) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "param转换对象后为空");
			return;
		}
		if(StringUtils.isEmpty(user.getSchoolid())||StringUtils.isEmpty(user.getParid())
				||StringUtils.isEmpty(user.getStuid())||StringUtils.isEmpty(user.getOpenid())
				||StringUtils.isEmpty(user.getWxorgid())||StringUtils.isEmpty(user.getMobile())
				||StringUtils.isEmpty(user.getTclx())||StringUtils.isEmpty(user.getUrl())) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "param里面的参数都不能为空");
			return;
		}
		isSch(user, jo);
		if(!jo.isEmpty()) {
			return;
		}
		isBind(user,jo);
		if(!jo.isEmpty()) {
			return;
		}
		isPar(user,jo);
		if(!jo.isEmpty()) {
			return;
		}
		isStu(user,jo);
		if(!jo.isEmpty()) {
			return;
		}
		isStuPar(user,jo);
		if(!jo.isEmpty()) {
			return;
		}
		List<SchoolCharge> list = getSchoolCharge(user, jo);
		if(!jo.isEmpty()) {
			return;
		}
		String id = UUID.randomUUID().toString().replaceAll("-", "");
		JSONObject slit = getSchoolChargeJson(list);
		control.setAttr("slist", slit);
		control.setAttr("user", user);
		control.setSessionAttr("wPay_user", id);
		control.getSession().setMaxInactiveInterval(SEC);
		try {
			RedisMgr.getInstance().setProp(id, JSON.toJSONString(user));
			RedisMgr.getInstance().expireProp(id, SEC);
			jo.put("errcode", 0);
			jo.put("errmsg", "sucess");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private JSONObject getSchoolChargeJson(List<SchoolCharge> list) {
		JSONObject json = new JSONObject();
		json.put("title", "选择套餐");
		JSONArray jrr= new JSONArray();
		
		JSONObject j;
		for (SchoolCharge sch : list) {
			j = new JSONObject(); 
			j.put("title", sch.getChargename());
			j.put("value", sch.getChargecode());
			jrr.add(j);
		}
		json.put("items", jrr);
		return json;
	}
	
	private boolean isValCode(String cid,String code){
		String id = "get_cid_code_"+cid+"_"+code;
		String _code = null;
		try {
			_code = RedisMgr.getInstance().getProp(id);
			if(code.equals(_code)){
				//删除code
				 RedisMgr.getInstance().delProp(id);
			}else{
				return false;
			}
		} catch (ClassNotFoundException | IOException e) {
			e.printStackTrace();
		}
		return true;
	}
	
	private void isSch(User user,JSONObject json) {
		Record record = Db.findFirst("select sch.schoolname from wx_middle_org m inner join jc_schoolinfo sch on m.orgid = sch.schoolid where m.wxorgid=? and m.orgid=?", user.getWxorgid(),user.getSchoolid());
		if(null==record) {
			json.put("errcode", 10000);
			json.put("errmsg", "学校不存在或者学校和公众号对应关系错误");
			return;
		}
		String schoolName = record.getStr("schoolname");
		if(StringUtils.isEmpty(schoolName)) {
			json.put("errcode", 10000);
			json.put("errmsg", "学校名称为空");
			return;
		}
		user.setSchoolName(schoolName);
	}
	
	/**
	 * 判断家长和学生的对应关系是否正常
	 * @param user
	 * @return
	 */
	private void isStuPar(User user,JSONObject json) {
		Record record = Db.findFirst("select sfsc from jc_stu_par where schoolid=? and parid=? and stuid=?",user.getSchoolid(),user.getParid(),user.getStuid());
		if(null==record) {
			json.put("errcode", 10000);
			json.put("errmsg", "学生和家长的对应关系不存在");
			return;
		}
		Integer sfsc = record.getInt("sfsc");
		if(null==sfsc||sfsc==1) {
			json.put("errcode", 10004);
			json.put("errmsg", "家长和学生关系处于删除状态");
			return;
		}
	}
	/**
	 * 判断家长信息是否正确，正确的话设置家长姓名
	 * @param user
	 * @return
	 */
	private void isPar(User user,JSONObject json) {
		Record record = Db.findById("jc_parentinfo", "parid", user.getParid());
		if(null==record) {
			json.put("errcode", 10000);
			json.put("errmsg", "家长信息不存在");
			return;
		}
		Integer sfsc = record.getInt("sfsc");
		if(null==sfsc||sfsc==1) {
			json.put("errcode", 10004);
			json.put("errmsg", "家长信息处于删除状态");
			return;
		}
		String lxdh = record.getStr("lxdh");
		if(!lxdh.equals(user.getMobile())) {
			json.put("errcode", 10004);
			json.put("errmsg", "家长手机号不匹配");
			return;
		}
		String jzxm = record.getStr("jzxm");
		if(StringUtils.isEmpty(jzxm)) {
			json.put("errcode", 10000);
			json.put("errmsg", "家长姓名为空");
			return;
		}
		user.setParName(jzxm);
		
	}
	
	/**
	 * 判断学生信息是否存在
	 * @param user
	 * @return
	 */
	private void isStu(User user,JSONObject json) {
		Record record = Db.findById("jc_studentinfo", "stuid", user.getStuid());
		if(null==record) {
			json.put("errcode", 10000);
			json.put("errmsg", "学生信息不存在");
			return;
		}
		Integer sfsc = record.getInt("sfsc");
		if(null==sfsc||sfsc==1) {
			json.put("errcode", 10004);
			json.put("errmsg", "学生信息处于删除状态");
			return;
		}
		String xm = record.getStr("xm");
		if(StringUtils.isEmpty(xm)) {
			json.put("errcode", 10000);
			json.put("errmsg", "学生姓名为空");
			return;
		}
		user.setStuName(xm);
	}
	
	/**
	 * 判断用户是否已经绑定，如果绑定判断绑定的手机号和微信openid和传入的是否一致
	 * @param wxorgid
	 * @param userid
	 * @param openid
	 * @param mobile
	 * @return
	 */
	private void isBind(User user,JSONObject json) {
		Record record = Db.findById("wx_middle_user", "wxorgid,userid", user.getWxorgid(),user.getParid());
		if(null==record) {
			json.put("errcode", 10000);
			json.put("errmsg", "家长未绑定");
			return;
		}
		String _openid = record.getStr("openid");
		if(!user.getOpenid().equals(_openid)) {
			json.put("errcode", 10004);
			json.put("errmsg", "微信用户唯一标示不匹配");
			return;
		}
		String _mobile = record.getStr("mobile");
		if(!user.getMobile().equals(_mobile)) {
			json.put("errcode", 10004);
			json.put("errmsg", "手机号码不匹配");
			return;
		}
	}
	
	private List<SchoolCharge> getSchoolCharge(User user,JSONObject json) {
		List<Record> list = Db.find("select b.chargecode,b.chargename,b.chargeprice,b.info from xzd_base_schoolcharge sc inner join xzd_base_charge b on sc.chargecode=b.chargecode where sc.schoolid=? and sc.tczt=? and b.tclx=?",user.getSchoolid(),"1",user.getTclx());
		if(null==list||list.isEmpty()) {
			json.put("errcode", 10004);
			json.put("errmsg", "当前学校未配置套餐");
			return null;
		}
		List<SchoolCharge> slist = new ArrayList<SchoolCharge>();
		String chargecode;
		String chargename;
		Double chargeprice;
		String info;
		SchoolCharge data;
		for (Record record : list) {
			chargecode = record.getStr("chargecode");
			chargename = record.getStr("chargename");
			chargeprice = record.getDouble("chargeprice");
			info = record.get("info");
			if(null==chargeprice||chargeprice==0) {
				json.put("errcode", 10000);
				json.put("errmsg", "套餐资费配置错误");
				return null;
			}
			data = new SchoolCharge();
			data.setChargecode(chargecode);
			data.setChargename(chargename+"(价格: "+chargeprice+"元/月)");
			data.setChargeprice(chargeprice);
			data.setInfo(info);
			slist.add(data);
		}
		return slist;
	}
	
	public void isYzm(String mobile,String mobileVal,String chargeCode,String month,Controller control,JSONObject json) {
		if(StringUtils.isEmpty(mobile)||StringUtils.isEmpty(mobileVal)
				||StringUtils.isEmpty(chargeCode)||StringUtils.isEmpty(month)) {
			System.out.println("mobile: "+mobile);
			System.out.println("mobileVal: "+mobileVal);
			System.out.println("chargeCode: "+chargeCode);
			System.out.println("month: "+month);
			json.put("errcode",10000);
			json.put("errmsg","所有参数都不能为空");
			return;
		}
		User user;
		Integer _month;
		String id = control.getSessionAttr("wPay_user");
		if(StringUtils.isEmpty(id)) {
			json.put("errcode",10004);
			json.put("errmsg","超时，请关闭当前页面重新进入购买页面");
			return;
		}
		String sessionMobile = null;
		try {
			String userJson = RedisMgr.getInstance().getProp(id);
			if(StringUtils.isEmpty(userJson)) {
				json.put("errcode",10004);
				json.put("errmsg","超时，请关闭当前页面重新进入购买页面");
				return;
			}
			user = JSON.parseObject(userJson, User.class);
			if(null!=user) {
				sessionMobile = user.getMobile();
			}
			
			_month = Integer.parseInt(month);
			if(null==_month||_month<1) {
				json.put("errcode",10004);
				json.put("errmsg","选择订购数量错误");
				return;
			}
			
		}catch (NumberFormatException e) {
			json.put("errcode",10004);
			json.put("errmsg","选择订购数量错误");
			return;
		}catch (Exception e) {
			json.put("errcode",10004);
			json.put("errmsg","超时，请关闭当前页面重新进入购买页面");
			logger.error("转换user对象失败", e);
			return;
		}
		if(StringUtils.isEmpty(sessionMobile)) {
			json.put("errcode",10004);
			json.put("errmsg","超时，请关闭当前页面重新进入购买页面");
			return;
		}
		if(!mobile.equals(sessionMobile)) {
			json.put("errcode",10004);
			json.put("errmsg","超时，请关闭当前页面重新进入购买页面");
			return;
		}
		getSchoolChargeParam(user, json);
		if(!json.isEmpty()) {
			return;
		}
		
		Map<String, String> map = new HashMap<String, String>();
		map.put("type", "wx_pay");
		map.put("mobile", mobile);
		map.put("yzm", mobileVal);
		
		String msg = HttpKit.get(CHECKCAPTCHAURL, map);
		try {
			JSONObject jsonObject = JSON.parseObject(msg);
			if(jsonObject.getInteger("errcode")==0) {
				RedisMgr.getInstance().setProp(id, JSON.toJSONString(user));
				RedisMgr.getInstance().expireProp(id, 20*60);
			}
			json.putAll(jsonObject);
		}catch (Exception e) {
			json.put("errcode",10004);
			json.put("errmsg","验证码错误");
			logger.error("到服务器验证输入的验证码失败",e);
			return;
		}
	}
	
	/**
	 * 判断套餐是否存在并提取支付配置信息
	 * @param schoolid
	 * @param chargeCode
	 * @return
	 */
	private void getSchoolChargeParam(User user,JSONObject json) {
		String configuration;
		Record record = Db.findById("xzd_base_schoolcharge", "schoolid,chargecode",user.getSchoolid(),user.getChargeCode());
		if(null==record) {
			json.put("errcode",10004);
			json.put("errmsg","当前学校未配置该套餐");
			return;
		}
		configuration = record.getStr("configuration");
		Record r = Db.findById("xzd_base_charge", "chargecode",user.getChargeCode());
		String info = r.getStr("info");//套餐说明
		if(StringUtils.isEmpty(info)) {
			info = r.getStr("chargename");//说明取不到就取套餐的名字
		}
		if(StringUtils.isEmpty(info)) {
			json.put("errcode",10004);
			json.put("errmsg","套餐信息配置错误");
			return;
		}
		user.setChargeInfo(info);
		
		Double chargetPrice = r.getDouble("chargeprice");
		if(null==chargetPrice||chargetPrice<=0) {
			json.put("errcode",10004);
			json.put("errmsg","套餐支付金额配置错误");
			return;
		}
		//一份的金额乘以份数在转换成分
		Double total = 0D;
		if(null!=user.getMonth()) {
			total = (user.getMonth()*chargetPrice)*100;
		}
		if(null!=user.getDays()) {
			total = chargetPrice*100;
		}
		Integer _total=total.intValue();
		if(_total<=0) {
			json.put("errcode",10004);
			json.put("errmsg","支付配置错误");
			return;
		}
		user.setAmount(_total);
		System.out.println("amount: "+user.getAmount());
		if(StringUtils.isEmpty(configuration)) {
			configuration = r.getStr("configuration");
		}
		if(StringUtils.isEmpty(configuration)) {
			json.put("errcode",10004);
			json.put("errmsg","支付配置错误");
			return;
		}
		try {
			JSONObject j = JSON.parseObject(configuration);
			Integer type = j.getInteger("type");
			if(type==1) {
				//微信
				String payWxorgid = j.getString("pay_wxorgid");
				if(StringUtils.isEmpty(payWxorgid)) {
					json.put("errcode",10000);
					json.put("errmsg","未找到用于支付的公众号");
					return;
				}
				OrgWxconfig config = OrgWxConfigService.getInstance().getWxConfig(payWxorgid);
				if(null==config) {
					json.put("errcode",10000);
					json.put("errmsg","未找到用于支付的公众号配置信息");
					return;
				}
				user.setPayWxorgid(payWxorgid);
				String appid = config.getAppId();
				String apiKey = config.getApiKey();
				String mchId = config.getMchId();
				if(StringUtils.isEmpty(appid)||StringUtils.isEmpty(apiKey)
						||StringUtils.isEmpty(mchId)) {
					System.out.println("appid: "+appid);
					System.out.println("apiKey: "+apiKey);
					System.out.println("mchId: "+mchId);
					json.put("errcode",10000);
					json.put("errmsg","支付公众号参数设置不正确");
					return;
				}
				user.setApiKey(apiKey);
				user.setAppId(appid);
				user.setMchId(mchId);
			}
		}catch (Exception e) {
			e.printStackTrace();
			logger.error(e);
			json.put("errcode",10004);
			json.put("errmsg","支付配置处理错误");
			return;
		}
	}
	
	public void xzdAuthorize(String cid, String code, String param,JSONObject jo,
			User user,HttpSession session) {
		if(StringUtils.isEmpty(code)||StringUtils.isEmpty(param)) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "所有参数均不能为空");
			return;
		}
		boolean b = isValCode(cid, code);
		if(!b) {
			jo.put("errcode", 10004);
			jo.put("errmsg", "code错误");
		}
		try {
			 user = JSON.parseObject(param, User.class);
		}catch (Exception e) {
			jo.put("errcode", 10004);
			jo.put("errmsg", "param参数错误");
			return;
		}
		if(null==user) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "param转换对象后为空");
			return;
		}
		String url = user.getUrl();
		try {
			url = URLDecoder.decode(url, "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "url转换失败");
			return;
		}
		user.setUrl(url);
		Integer month = user.getMonth();
		Integer days = user.getDays();
		if(StringUtils.isEmpty(user.getSchoolid())||StringUtils.isEmpty(user.getParid())
				||StringUtils.isEmpty(user.getStuid())||StringUtils.isEmpty(user.getOpenid())
				||StringUtils.isEmpty(user.getWxorgid())||StringUtils.isEmpty(user.getMobile())
				||StringUtils.isEmpty(user.getChargeCode())||StringUtils.isEmpty(user.getUrl())) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "param里面的参数都不能为空");
			return;
		}
		if((null==month||month<1)&&(null==days||days<1)) {
			jo.put("errcode", 10000);
			jo.put("errmsg", "数量和天数必须填写一个");
			return;
		}
		if(null!=month) {
			if(month!=1&&month!=3&&month!=6&&month!=12) {
				jo.put("errcode", 10000);
				jo.put("errmsg", "购买数量不正确");
				return;
			}
		}
		if(null!=days) {
			if(days<1) {
				jo.put("errcode", 10000);
				jo.put("errmsg", "购买天数不正确");
				return;
			}
		}
		try {
			isSch(user, jo);
			if(!jo.isEmpty()) {
				return;
			}
			isBind(user,jo);
			if(!jo.isEmpty()) {
				return;
			}
			isPar(user,jo);
			if(!jo.isEmpty()) {
				return;
			}
			isStu(user,jo);
			if(!jo.isEmpty()) {
				return;
			}
			isStuPar(user,jo);
			if(!jo.isEmpty()) {
				return;
			}
			
			getSchoolChargeParam(user,jo);
			if(!jo.isEmpty()) {
				return;
			}
			String id = UUID.randomUUID().toString().replaceAll("-", "");
			
			session.setAttribute("wPay_user", id);
			session.setMaxInactiveInterval(SEC);
			RedisMgr.getInstance().setProp(id, JSON.toJSONString(user));
			RedisMgr.getInstance().expireProp(id, SEC);
			jo.put("errcode", 0);
			jo.put("errmsg", user.getPayWxorgid());
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getStackTrace());
			jo.put("errcode", 10008);
			jo.put("errmsg", "系统错误");
		}
	}
	
}